package com.maimang.platform.dsp.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.maimang.platform.common.entity.SysApiLog;
import com.maimang.platform.common.entity.SysUser;
import com.maimang.platform.common.service.SysApiLogService;
import com.maimang.platform.common.service.SysUserService;
import com.maimang.platform.common.utils.DateUtils;
import com.maimang.platform.common.utils.RedisUtils;
import com.maimang.platform.common.utils.ShiroUtils;
import com.maimang.platform.enums.BusinessStatus;
import com.maimang.platform.enums.OperatorType;
import com.maimang.platform.lang.StringUtils;
import com.maimang.platform.tool.ToolAddress;
import com.maimang.platform.tool.ToolIP;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.Map;

/**
 * @author Rocky
 * @version 1.0.0
 * @classname ApiService
 * @description <br>头条系专用API接口请求工具类</br>
 * @date 2019-07-23 12:00
 * @email jintaozhao@qq.com
 */
// @Service("apiService")
@Component
public class ApiService {

	private static final Logger log = LoggerFactory.getLogger(ApiService.class);

	@Autowired
	private SysApiLogService sysApiLogService;

	@Autowired
	private SysUserService sysUserService;


	/**
	 * @param url         请求地址
	 * @param accessToken access_token
	 * @param param       请求参数
	 * @return
	 */
	public JSONObject sendGet(String url, String accessToken, Map param) {
		return sendHttp(url, "GET", true, accessToken, param);
	}

	/**
	 * 针对access_token refresh_token请求调用的方法
	 *
	 * @param url   请求地址
	 * @param param 请求参数
	 * @return
	 */
	public JSONObject sendPost(String url, Map param) {
		return sendHttp(url, "POST", false, StringUtils.EMPTY, param);
	}

	/**
	 * @param url         请求地址
	 * @param accessToken access_token
	 * @param param       请求参数
	 * @return
	 */
	public JSONObject sendPost(String url, String accessToken, Map param) {
		return sendHttp(url, "POST", true, accessToken, param);
	}

	/**
	 * @param url         请求地址
	 * @param method      请求方法 GET/POST
	 * @param needToken   是否需要access_token参数
	 * @param accessToken access_token
	 * @param param       请求参数
	 * @return
	 */
	private JSONObject sendHttp(String url, String method, boolean needToken, String accessToken, Map param) {
		if (StringUtils.isEmpty(url)) {
			log.error("请求URL地址为空，请检查");
			return JSON.parseObject("请求URL地址不能为空");
		}
		if (needToken && StringUtils.isEmpty(accessToken)) {
			log.error("请求头Access-Token不能为空");
			return JSON.parseObject("请求头Access-Token不能为空");
		}

		return sendRequest(url, method, needToken, accessToken, param);
	}

	public void getIp() {
		System.out.println(ShiroUtils.getIp());
	}

	/**
	 * @param url         请求URL
	 * @param method      请求方法
	 * @param needToken   是否需要access_token
	 * @param accessToken access_token
	 * @param param       请求参数
	 * @return
	 */
	private JSONObject sendRequest(String url, String method, boolean needToken, String accessToken, Map param) {
		String errorMsg = "调用ApiService.{} {}, url={}, param={}, method={}";
		String methodName = method == "GET" ? "sendGet" : "sendPost";

		// 开始记录日志
		SysApiLog apiLog = new SysApiLog();
		apiLog.setUserType(OperatorType.MANAGE.ordinal());
		apiLog.setApiUrl(url);
		apiLog.setRequestMethod(method);
		apiLog.setMethod("Marketing API接口");
		apiLog.setAccessToken(accessToken);
		// 请求的地址
		String hostIp = ToolIP.getHostIp();
		apiLog.setUserHost(hostIp);
		String address = ToolAddress.getRealAddressByIP(hostIp);
		apiLog.setUserLocation(address);

		if (!RedisUtils.exists("user")) {
			RedisUtils.set("user", sysUserService.selectUserById(1L));
		}
		SysUser curUser = (SysUser) RedisUtils.get("user");
		if (curUser != null) {
			apiLog.setUserId(curUser.getUserId());
			apiLog.setUserName(curUser.getUserName());
			if (StringUtils.isNotEmpty(curUser.getDeptName())) {
				apiLog.setDeptName(curUser.getDeptName());
			}
			if (curUser.getDeptId() != null) {
				apiLog.setDeptId(curUser.getDeptId().toString());
			}
		}


		apiLog.setRequestParam(JSONObject.toJSONString(param));
		long startTime = System.currentTimeMillis();

		// 构造请求
		HttpEntityEnclosingRequestBase httpEntity = new HttpEntityEnclosingRequestBase() {
			@Override
			public String getMethod() {
				return method;
			}
		};
		httpEntity.setURI(URI.create(url));
		if (needToken) {
			if (StringUtils.isNotEmpty(accessToken)) {
				httpEntity.setHeader("Access-Token", accessToken);
			}
		}
		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;

		try {
			client = HttpClientBuilder.create().build();
			httpEntity.setEntity(new StringEntity(JSONObject.toJSONString(param), ContentType.APPLICATION_JSON));

			response = client.execute(httpEntity);
			if (response != null && response.getStatusLine().getStatusCode() == 200) {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
				StringBuffer result = new StringBuffer();
				String line = "";
				while ((line = bufferedReader.readLine()) != null) {
					result.append(line);
				}
				bufferedReader.close();

				// 更新日志
				apiLog.setStatus(BusinessStatus.SUCCESS.ordinal());
				long times = System.currentTimeMillis() - startTime;
				apiLog.setRunningTime("总共耗时：" + times + "毫秒");
				apiLog.setOperTime(DateUtils.getNowDate());
				JSONObject resultObj = JSONObject.parseObject(result.toString());
				apiLog.setResponseMessage(JSON.toJSONString(resultObj));

				if (resultObj != null) {
					String requestId = resultObj.getString("request_id");
					apiLog.setRequestId(requestId);
					Integer status = resultObj.getInteger("code");
					apiLog.setStatus(status);
					if (status != 0) {
						sysApiLogService.insertSysApiLog(apiLog);
					}
				}

				return resultObj;
			}
		} catch (ClientProtocolException e) {
			errorMsg = StringUtils.format(errorMsg, methodName, "ClientProtocolException", url, param);
			log.error(errorMsg, e);
		} catch (IOException e) {
			errorMsg = StringUtils.format(errorMsg, methodName, "IOException", url, param);
			log.error(errorMsg, e);
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				client.close();
			} catch (IOException e) {
				errorMsg = StringUtils.format(errorMsg, methodName, "IOException", url, param);
				log.error(errorMsg, e);
			}
		}
		return null;
	}

}
